template <typename T, class VST>
void travPost_R(BinNodePosi(T) p, VST &visit) {
	if(!p) return;

	travPost_R(p->lc, visit);
	travPost_R(p->rc, visit);
	visit(p->data);
}

template <typename T>
static void gotoHLVFL(std::stack<BinNodePosi(T)> &s) {
	BinNodePosi(T) p;
	while (s.top())
	{
		p = s.top();
		if(HasLChild(*p)) {
			if(HasRChild(*p)) {
				s.push(p->rc);
			}
			s.push(p->lc);
		}
		else {
			s.push(p->rc);
		}
	}
	s.pop();
}

template <class T, class VST>
void travPost_I1(BinNodePosi(T) p, VST &visit) {
	std::stack<BinNodePosi(T)> s;
	if(p) s.push(p);

	while(!s.empty()) {
		// s.top() is either the parent of p or the sibling of p except the first one
		if(s.top() != p->parent) {
			gotoHLVFL(s);
		}

		p = s.top();
		s.pop();

		visit(p->data);
	}
}

template <typename T, class VST>
void travPost_I2(BinNodePosi(T) p, VST &visit) {
	if(!p) return;

	std::stack<BinNodePosi(T) > s, candidate;
	s.push(p);
	while(!s.empty()) {
		p = s.top();
		s.pop();
	
		if(!candidate.empty() && candidate.top() + 0 == p) {
			visit(p->data);
			candidate.pop();
			// omit "else" judgement
			continue;
		}
		
		// else judgement
		if(p->rc) s.push(p->rc);
		if(p->lc) s.push(p->lc);
		s.push(p);
		candidate.push(p);
	}

}
